<?php

if (!defined("PATH_HD"))
    exit('No direct script access allowed');
// .-----------------------------------------------------------------------------------
// |  Software: [HDPHP framework]
// |   Version: 2013.01
// |      Site: http://www.hdphp.com
// |-----------------------------------------------------------------------------------
// |    Author: 向军 <houdunwangxj@gmail.com>
// | Copyright (c) 2012-2013, http://houdunwang.com. All Rights Reserved.
// |-----------------------------------------------------------------------------------
// |   License: http://www.apache.org/licenses/LICENSE-2.0
// '-----------------------------------------------------------------------------------

/**
 * 系统核心函数库
 * @package     core
 * @author      后盾向军 <houdunwangxj@gmail.com>
 */

/**
 * 加载核心模型
 * @param type $tableName           表名
 * @param type boolean  $full       是否为全表名
 * @return Model                    返回模型对象
 */
function M($tableName = null, $full = null) {
    return new Model($tableName, $full);
}

/**
 * 加载扩展模型文件
 * @param $tabname	表名
 */
function K($model) {
    $modelArr = get_model_file($model);
    $fileExists = load_file($modelArr[0]); //加载类文件
    if (!$fileExists) {
        error(L("functions_k_is_file") . $modelArr[0], false); //还没有定义模型文件
    }
    $modelClass = $modelArr[1] . 'Model';
    if (!class_exists($modelClass, false)) {
        error(L("functions_k_error"), false); //模型类定义有误
    }
    $model = new $modelClass($modelArr[1]);
    return $model;
}

/**
 * 获得关联模型
 * @param type $model
 */
function R($tableName = null, $full = null) {
    return new relationModel($tableName, $full);
}

/**
 * 获得视图模型
 * @param type $model
 */
function V($tableName = null, $full = null) {
    return new ViewModel($tableName, $full);
}

/**
 * 根据配置文件的URL参数重新生成URL地址
 * @param type $arg
 * @param type $args
 * $args = "nid=2&cid=1"
 * $args=array("nid"=>2,"cid"=>1)
 */
function U($pathinfo, $args = array()) {
    if (preg_match("/^https?:\/\//", $pathinfo))
        return $pathinfo;
    $end = strpos($pathinfo, '.php'); //是否指定单入口
    if ($end) {
        $web = __ROOT__ . '/' . substr($pathinfo, 0, $end + 4);
        $pathinfo = substr($pathinfo, $end + 4);
    } else {
        $web = __WEB__;
    }
//参数$args为字符串时转数组
    if (is_string($args)) {
        parse_str($args, $args);
    }
    $parseUrl = parse_url(trim($pathinfo, '/'));
    $path = trim($parseUrl['path'], '/');
//解析字符串的?后参数 并与$args合并
    if (isset($parseUrl['query'])) {
        parse_str($parseUrl['query'], $query);
        $args = array_merge($query, $args);
    }
//组合出索引数组  将?后参数与$args传参
    $gets = array();
    if (is_array($args)) {
        foreach ($args as $n => $q) {
            array_push($gets, $n);
            array_push($gets, $q);
        }
    }
    $vars = explode("/", $path);
//入口文件类型
    $urlType = C("URL_TYPE"); //1 pathinfo 2 get
    switch ($urlType) {
        case 1:
            $root = $web . '/'; //入口位置
            break;
        case 2:
            $root = $web . '?';
            break;
    }
//组合出__WEB__后内容
    $data = array();
    switch (count($vars)) {
        case 2://应用
            $data[] = C("VAR_CONTROL");
            $data[] = array_shift($vars);
            $data[] = C("VAR_METHOD");
            $data[] = array_shift($vars);
            break;
        case 1://方法
            $data[] = C("VAR_CONTROL");
            $data[] = CONTROL;
            $data[] = C("VAR_METHOD");
            $data[] = array_shift($vars);
            break;
        default://应用组及其他情况
            $data[] = C("VAR_APP");
            $data[] = array_shift($vars);
            $data[] = C("VAR_CONTROL");
            $data[] = array_shift($vars);
            $data[] = C("VAR_METHOD");
            $data[] = array_shift($vars);
            if (is_array($vars)) {
                foreach ($vars as $v) {
                    $data[] = $v;
                }
            }
    }
    $varsAll = array_merge($data, $gets); //合并GET参数
    $url = '';

    switch ($urlType) {
        case 1:
            foreach ($varsAll as $value) {
                $url.=C('PATHINFO_Dli') . $value;
            }
            $url = str_replace(array("/" . C("VAR_APP") . "/", "/" . C("VAR_CONTROL") . "/", "/" . C("VAR_METHOD") . "/"), "/", $url);
            $url = substr($url, 1);
            break;
        case 2:
            foreach ($varsAll as $k => $value) {
                if ($k % 2) {
                    $url.='=' . $value;
                } else {
                    $url.='&' . $value;
                }
            }
            $url = substr($url, 1);
            break;
    }
    $pathinfo_html = $urlType === 1 ? '.' . trim(C("PATHINFO_HTML"), '.') : ''; //伪表态后缀如.html
    return $root . url::toRoute($url) . $pathinfo_html;
}

/**
 * 快速缓存  以文件形式缓存
 * @param type $name    缓存名称
 * @param type $value   缓存值
 * @param type $path    缓存目录
 */
function F($name, $value = false, $path = PATH_TEMP_CACHE) {
    $_cache = array();
    $name = md5($name);
    $cacheFile = $path . '/' . $name . '.php';
    if (is_null($value)) {
        if (is_file($cacheFile)) {
            unlink($cacheFile);
            unset($_cache[$name]);
        }
    }
    if ($value == false) {
        if (isset($_cache[$name]))
            return $_cache[$name];
        return is_file($cacheFile) ? include $cacheFile : null;
    }
    $data = "<?php if(!defined('PATH_HD'))exit;\nreturn " . strip_space(var_export($value, true)) . ";\n?>";
    is_dir($path) || dir_create($path);
    if (!file_put_contents($cacheFile, $data)) {
        return false;
    }
    $_cache[$name] = $data;
    return true;
}

/**
 * 缓存处理
 * @param string $name          缓存名称
 * @param mixed $value          缓存内容
 * @param int $expire           缓存时间
 * @param type $options         缓存对象参数    如array("dir"=>"cache","driver"=>"memcache")
 * @return type
 */
function S($name, $value = false, $expire = null, $options = array()) {
    static $_data = array();
    $cacheObj = cache::init($options);
    if (is_null($value)) {
        return $cacheObj->del($name);
    }
    $driver = isset($options['driver']) ? $options['driver'] : '';
    $key = $name . $driver;
    if ($value === false) {
        if (isset($_data[$key])) {
            return $_data[$key];
        } else {
            return $cacheObj->get($name);
        }
    }
    $cacheObj->set($name, $value, $expire);
    $_data[$key] = $value;
    return true;
}

/**
 * 获得模型文件
 */
function get_model_file($path) {
    $path = rtrim($path, '/');
    $path = str_ireplace("Model.php", '', $path);
    $path = str_replace(C("MODEL_FIX"), '', $path);
    $pathArr = explode('/', $path);
    $arr = array();
    switch (count($pathArr)) {
        case 1:
            $arr['app_group'] = '';
            $arr['app'] = PATH_APP . '/';
            $arr['model'] = $pathArr[0];
            break;
        case 2:
            $arr['app_group'] = PATH_APP_GROUP . '/';
            $arr['app'] = $pathArr[0] . '/';
            $arr['model'] = $pathArr[1];
            break;
        default:
            return array($path . C("MODEL_FIX") . '.php', array_pop($pathArr));
    }
    $modelFile = $arr['app_group'] . $arr['app'] . 'model/' . ucfirst($arr['model']) . C("MODEL_FIX") . '.php';
    return array($modelFile, array_pop($pathArr));
}

/**
 * 记录缓存读写与数据库操作次数
 * @param type $type    类型
 * @param type $step    计数
 *
 */
function N($name, $num = NULL) {
    //记数静态变量
    static $data = array();
    if (!isset($data[$name])) {
        $data[$name] = 0;
    }
    if (is_null($num)) {//获得计数
        return $data[$name];
    } else {//更改缓存记数
        $data[$name] +=(int) $num;
    }
}

/**
 * 加载控制器
 */
function get_control_file($path) {
    $path_r = str_replace(C("CONTROL_FIX") . ".php", '', rtrim($path, '/'));
    $path = str_replace(C("CONTROL_FIX"), '', $path_r);
    $pathArr = explode('/', $path);
    $arr = array();
    switch (count($pathArr)) {
        case 1:
            $arr['app_group'] = '';
            $arr['app'] = PATH_APP . '/';
            $arr['control'] = $pathArr[0];
            break;
        case 2:
            $arr['app_group'] = PATH_APP_GROUP . '/';
            $arr['app'] = $pathArr[0] . '/';
            $arr['control'] = $pathArr[1];
            break;
        default:
            return array($path . C("CONTROL_FIX") . '.php', array_pop($pathArr));
    }
    $controlFile = $arr['app_group'] . $arr['app'] . 'control/' . $arr['control'] . C("CONTROL_FIX") . '.php';
    return array($controlFile, array_pop($pathArr));
}

/**
 * 获得控制器对象
 * @param type $control         控制器名，可以为module.control形式调用其他模块的控制器
 */
function control($control) {
    
    $controlArr = get_control_file($control);
    static $_control = array();
    $name = md5($controlArr[0]);
    if (isset($_control [$name])) {
        return $_control [$name];
    }
//控制器文件
    $controlFile = $controlArr[0];
    $controlClass = $controlArr[1] . C("CONTROL_FIX");
    if (load_file($controlFile) && class_exists($controlClass, false)) {
        $_control [$name] = new $controlClass();
        return $_control [$name];
    }
    return false;
}

/**
 * SESSION处理
 * @param type $name
 * @param type $value
 */
function session($name, $value = '') {
    static $_start = false;
    if ($_start === false) {
        $_start = true;
        session_id() || session_start();
    }
//清空SESSION
    if (is_null($name)) {
        $_SESSION = array();
        session_unset();
        session_destroy();
    } elseif (is_null($value)) {//删除SESSION
        unset($_SESSION[$name]);
    } elseif (empty($value)) {//获得SESSION赋值
        switch (strtolower($name)) {
            case "[parse]"://停止SESSION
                session_write_close();
                break;
        }
        return isset($_SESSION[$name]) ? $_SESSION[$name] : null;
    } else {//赋值SESSION
        $_SESSION[$name] = $value;
    }
}

/**
 * 生成序列字符串
 * @param type $var
 */
function md5_d($var) {
    return md5(serialize($var));
}

/**
 * 批量创建目录
 * @param $dirArr	目录名数组
 * @param $auth		权限
 */
function dir_create($dirName, $auth = 0755) {
    $dirName = str_replace("\\", "/", $dirName);
    $dirPath = rtrim($dirName, '/');
    if (is_dir($dirPath))
        return true;
    $dirs = explode('/', $dirPath);
    $dir = '';
    foreach ($dirs as $v) {
        $dir .= $v . '/';
        if (!is_dir($dir)) {
            @mkdir($dir, $auth, true) ;
        }
    }
    return is_dir($dirPath);
}

/**
 * 生成对象 或执行方法
 * @param class $class      类
 * @param type $method   方法
 * @param type $args        参数
 * @return class
 */
function O($class, $method = '', $args = array()) {
    static $result = array();
    $name = empty($args) ? $class . $method : $class . $method . md5_d($args);
    if (!isset($result [$name])) {
        $class = new $class ();
        if (!empty($method) && method_exists($class, $method)) {
            if (!empty($args)) {
                $result [$name] = call_user_func_array(array(&$class, $method), $args);
            } else {
                $result [$name] = $class->$method();
            }
        } else {
            $result [$name] = $class;
        }
    }
    return $result [$name];
}

/**
 *
 * 加载文件或获得加载过的所有文件组成的数组
 * @param string 	$file
 */
function load_file($file = "") {
    static $fileArr = array();
    if (empty($file)) {
        return $fileArr;
    }
    $name = md5($file); //保存到数组中的MD5文件名\
    if (isset($fileArr[$name])) {//缓存中存在  即代表文件已经加载  停止加载
        return true;
    }
    if (!file_exists_case($file)) {
        return false;
    }
    require $file; //载入文件
    $fileArr[$name] = array(); //保存到静态变量中
    $fileArr[$name]['path'] = $file;
    if (true) {
        $fileArr[$name]['time'] = number_format(microtime(true) - NOW_MICROTIME, 4);
        if (function_exists("memory_get_usage")) {
            $fileArr [$name]['memory'] = number_format(memory_get_usage() / pow(1024, 1), 0) . "kb";
        } else {
            $fileArr [$name]['memory'] = "0kb";
        }
    }
    return true;
}

/**
 * 区分大小写的判断文件判断
 * @param string $file  需要判断的文件
 * @return boolean
 */
function file_exists_case($file) {
    if (is_file($file)) {
//windows环境下检测文件大小写
        if (IS_WIN && C("CHECK_FILE_CASE")) {
            if (basename(realpath($file)) != basename($file)) {
                return false;
            }
        }
        return true;
    }
    return false;
}

/**
 * 移除URL中的指定GET变量
 * @param string $var  要移除的GET变量名称
 * @param string $url   操作的url
 * @return string   移除GET变量后的URL地址
 */
function url_remove_param($var, $url = null) {
    return url::urlRemoveParam($var, $url);
}

/**
 * 根据大小返回标准单位 KB  MB GB等
 */
function get_size($size, $decimals = 2) {
    switch (true) {
        case $size >= pow(1024, 3):
            return round($size / pow(1024, 3), $decimals) . " GB";
        case $size >= pow(1024, 2):
            return round($size / pow(1024, 2), $decimals) . " MB";
        case $size >= pow(1024, 1):
            return round($size / pow(1024, 1), $decimals) . " KB";
        default:
            return $size . 'B';
    }
}

/**
 * 数组转为常量
 * @param ARRAY 	$arr
 */
function array_defined($arr) {
    foreach ($arr as $k => $v) {
        $k = strtoupper($k);
        if (is_string($v)) {
            define($k, $v);
        } elseif (is_numeric($v)) {
            defined($k, $v);
        } elseif (is_bool($v)) {
            $v = $v ? 'true' : 'false';
            define($k, $v);
        }
    }
    return true;
}

/**
 * 载入或设置配置顶
 * @param string	$name
 * @param string 	$value
 */
function C($name = null, $value = null) {
    static $config = array();
    if (is_null($name)) {
        return $config;
    }
    if (is_string($name)) {
        $name = strtolower($name);
        if (!strstr($name, '.')) {
            if (is_null($value)) {
                if (isset($config[$name]) && !is_array($config[$name])) {
                    $config[$name] = trim($config[$name]);
                }
                return isset($config [$name]) && !empty($config[$name]) ? $config [$name] : null;
            }
//加载文件如语言包
            if ($name == 'language') {
                $common_language = PATH_COMMON_LANGUAGE . '/' . $value . '.php';
                $app_language = PATH_LANGUAGE . '/' . $value . '.php';
                if (is_file(is_file($app_language))) {
                    L(include $app_language);
                } elseif (is_file($common_language)) {
                    L(include $common_language);
                }
            }
            $config [$name] = $value;
            return $config[$name];
        }
//二维数组
        $name = array_change_key_case_d(explode(".", $name), 0);
        if (is_null($value)) {
            return isset($config [$name[0]] [$name[1]]) ? $config [$name[0]][$name[1]] : null;
        }
        $config [$name[0]] [$name[1]] = $value;
    }
    if (is_array($name)) {
        $config = array_merge($config, array_change_key_case_d($name, 0));
        return true;
    }
}

//加载语言处理
function L($name = null, $value = null) {
    static $languge = array();
    if (is_null($name)) {
        return $languge;
    }
    if (is_string($name)) {
        $name = strtolower($name);
        if (!strstr($name, '.')) {
            if (is_null($value))
                return isset($languge [$name]) ? $languge [$name] : null;
            $languge [$name] = $value;
            return $languge[$name];
        }
//二维数组
        $name = array_change_key_case_d(explode(".", $name), 0);
        if (is_null($value)) {
            return isset($languge [$name[0]] [$name[1]]) ? $languge [$name[0]][$name[1]] : null;
        }
        $languge [$name[0]] [$name[1]] = $value;
    }
    if (is_array($name)) {
        $languge = array_merge($languge, array_change_key_case_d($name));
        return true;
    }
}

/**
 * 系统运行时加载的文件 是否在框架CORE目录中paths.php配置中
 * @staticvar array $files
 * @param type $className
 * @return type
 */
function auto_load_system_file($className) {
    static $files = array();
    if (is_array($className)) {
        $files = array_merge($files, array_change_key_case_d($className));
    } else {
        $name = strtolower($className);
        return isset($files[$name]) ? $files[$name] : false;
    }
}

//记录编译文件
function tpl_compile($tplFile = null) {
    static $file = array();
    if (is_null($tplFile))
        return $file;
    $file[] = $tplFile;
}

/**
 * 将数组键名变成大写或小写
 * @param type $arr
 * @param int   $type   转为大小写方式    1大写   0小写
 */
function array_change_key_case_d($arr, $type = 0) {
    $function = $type ? 'strtoupper' : 'strtolower';
    $newArr = array(); //格式化后的数组
    if (!is_array($arr) || empty($arr))
        return $newArr;
    foreach ($arr as $k => $v) {
        $k = $function($k);
        if (is_array($v)) {
            $newArr[$k] = array_change_key_case_d($v, $type);
        } else {
            $newArr[$k] = $v;
        }
    }
    return $newArr;
}

/**
 * 不区分大小写检测数据键名是否存在
 */
function array_key_exists_d($key, $arr) {
    return array_key_exists(strtolower($key), array_change_key_case_d($arr));
}

/**
 * 将数组中的值全部转为大写或小写
 * @param type $arr
 * @param type $type    1值大写 0值小写
 * @return type
 */
function array_change_value_case($arr, $type = 0) {
    $function = $type ? 'strtoupper' : 'strtolower';
    $newArr = array(); //格式化后的数组
    foreach ($arr as $k => $v) {
        if (is_array($v)) {
            $newArr[$k] = array_change_value_case($v, $type);
        } else {
            $newArr[$k] = $function($v);
        }
    }

    return $newArr;
}

/**
 * 多个PHP文件合并
 * @param array $filenameArr    文件
 * @param string $toFile        合并后的新文件
 * @param type $delSpace        是否删除注释及空格
 */
function php_merge($filenameArr, $toFile, $delSpace = false) {
    $saveDir = dirname($toFile);
    dir_create($saveDir);
    if (!is_array($filenameArr)) {
        $filenameArr = array($filenameArr);
    }
    $str = ''; //格式化后的内容
    $data = ''; //修复后的单个文件数据
    foreach ($filenameArr as $file) {
        $data = trim(file_get_contents($file));
        $data = substr($data, - 2) == '?>' ? $data : $data . "\t?>";
        $str.= strip_space($data);
    }
    $str = '<?php if(!defined("PATH_HD")){exit("No direct script access allowed");}define("TEMP_FILE_EXISTS",1);?>' . $str;
    @file_put_contents($toFile, $str) || error($saveDir . "目录不可写,系统运行失败", false);
    return $str;
}

/**
 * 去空格，去除注释包括单行及多行注释
 * $data    用于操作的数据内容
 */
function strip_space($content) {
    $str = ""; //合并后的字符串
    $data = token_get_all($content);
    $end = false; //没结束如$v = "hdphp"中的等号;
    for ($i = 0, $count = count($data); $i < $count; $i++) {
        if (is_string($data[$i])) {
            $end = false;
            $str.=$data[$i];
        } else {
            switch ($data[$i][0]) {//检测类型
//忽略单行多行注释
                case T_COMMENT:
                case T_DOC_COMMENT:
                    break;
//去除格
                case T_WHITESPACE:
                    if (!$end) {
                        $end = true;
                        $str.=" ";
                    }
                    break;
//定界符开始
                case T_START_HEREDOC:
                    $str.="<<<HDPHP\n";
                    break;
//定界符结束
                case T_END_HEREDOC:
                    $str.="HDPHP;\n";
//类似str;分号前换行情况
                    for ($m = $i + 1; $m < $count; $m++) {
                        if (is_string($data[$m]) && $data[$m] == ';') {
                            $i = $m;
                            break;
                        }
                        if ($data[$m] == T_CLOSE_TAG) {
                            break;
                        }
                    }
                    break;

                default:
                    $end = false;
                    $str.=$data[$i][1];
            }
        }
    }
    return $str;
}

/**
 * 获得常量
 * @param   string  $name   常量名称，默认为获得所有常量
 * @param   void    $value  常量不存在时的返回值
 * @param   string  $type   常量类型，默认为用户自定义常量,参数为true获得所有常量
 * @throws  array   常量数组
 */
function get_defines($name = "", $value = null, $type = 'user') {
    if ($name) {
        $const = get_defined_constants();
        return defined($name) ? $const[$name] : $value;
    }
    $const = get_defined_constants(true);
    return $type === true ? $const : $const[$type];
}

/**
 * 抛出异常
 * @param type $msg     错误信息
 * @param type $type    异常类
 * @throws type
 */
function throw_exception($msg, $type = "exceptionHD") {
    if (class_exists("exceptionHD")) {
        throw new $type($msg);
    } else {
        error($msg);
    }
}

/**
 * 输出错误信息
 * @param string   $error  错误信息内容
 * @param boolean  是否显示出错文件与行号
 */
function error($error, $showFile = true) {
    $exception = array(); //错误内容
    $backtrace = debug_backtrace();
    $exception ['message'] = "<b>[ERROR]</b> " . $error . "<br/>";
    if ($showFile) {
        $exception['message'].="\t<b>[FILE]</b> " . $backtrace[0]['file'] . "<br/>";
        $exception['message'].="\t<b>[LINE]</b> " . $backtrace[0]['line'] . "<br/>";
    }
    log::write(strip_tags($exception['message'])); //写入日志
    if (!C("DEBUG")) {
        $e['message'] = C("ERROR_MESSAGE") .
                "\t\t <span style='color:#666; font-weight:normal;'>
                    " . L("functions_error_debug") . "
                    </span>"; //查看详细错误信息方法有两种： ① 查看网站日志文件  ② 开启调试模式
        include C("ERROR_FILE");
        exit;
    }
    $e ['message'] = $exception['message'];
    include (PATH_HD_TPL . '/hd_error.html');
    debug::show("app_start", "app_end");
    exit;
}

/**
 * 打印输出数据
 * @param void $var
 */
function show($var) {
    echo "<pre>" . htmlspecialchars(print_r($var, true), ENT_QUOTES) . "</pre>";
}

/**
 * 打印输出数据|show的别名
 * @param void $var
 */
function p($var) {
    show($var);
}

/**
 * 打印输出数据|show的别名
 * @param void $var
 */
function dump($var) {
    show($var);
}

/**
 * 跳转网址
 * @param type $url 跳转url
 * @param type $time 跳转时间
 */
function go($url, $time = 0, $msg = '') {

    $url = U($url);
    if (!headers_sent()) {
        $time == 0 ? header("Location:" . $url) : header("refresh:{$time};url={$url}");
        exit($msg);
    } else {
        echo "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
        if ($time)
            exit($msg);
    }
}

/**
 * 将字符串格式路径转为URL  如admin/user/add 转为网址/应用组/应用/模块/控制器/方法
 * @param type $path
 */
//function get_url($path = '') {
//    if (preg_match('/http:\/\/|https:\/\//i', $path))
//        return $path;
//    $url = ''; //URL地址
//    $pathArr = array_filter(explode('/', trim($path, '/')));
//    switch (count($pathArr)) {
//        case 0:
//            $url = __APP__;
//            break;
//        case 1:
//            $url = __CONTROL__ . '/' . $pathArr[0];
//            break;
//        case 2:
//            $url = __APP__ . '/' . $pathArr[0] . '/' . $pathArr[1];
//            break;
//        case 3:
//            $url = __WEB__ . '/' . $pathArr[0] . '/' . $pathArr[1] . '/' . $pathArr[2];
//            break;
//        default:
//            $url = $path;
//            break;
//    }
//    return $url;
//}

/**
 * 获得客户端IP地址
 * @staticvar type $realip
 * @return type
 */
function ip_get_client($type = 0) {
    $ip = ''; //保存客户端IP地址
    if (isset($_SERVER)) {
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            $ip = $_SERVER["REMOTE_ADDR"];
        }
    } else {
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        } else if (getenv("HTTP_CLIENT_IP")) {
            $ip = getenv("HTTP_CLIENT_IP");
        } else {
            $ip = getenv("REMOTE_ADDR");
        }
    }
    $long = ip2long($ip);
    $clientIp = $long ? array($ip, $long) : array("0.0.0.0", 0);
    return $clientIp[$type];
}

/**
 * 是否为AJAX提交
 * @return boolean
 */
function ajax_request() {
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
        return true;
    return false;
}

/**
 * 对数组或字符串进行转义处理，数据可以是字符串或数组及对象
 * @param void $data
 * @return type
 */
function addslashes_d($data) {
    if (is_string($data)) {
        return addslashes($data);
    }
    if (is_numeric($data)) {
        return $data;
    }
    if (is_array($data)) {
        $var = array();
        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $var[$k] = addslashes_d($v);
                continue;
            } else {
                $var[$k] = addslashes($v);
            }
        }
        return $var;
    }
}

/**
 * 去除转义
 * @param type $data
 * @return type
 */
function stripslashes_d($data) {
    if (empty($data)) {
        return $data;
    } elseif (is_string($data)) {
        return stripslashes($data);
    } elseif (is_array($data)) {
        $var = array();
        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $var[$k] = stripslashes_d($v);
                continue;
            } else {
                $var[$k] = stripslashes($v);
            }
        }
        return $var;
    }
}

/**
 * 将数组转为字符串表示形式
 * @param array $array  数组
 * @param number $level 等级不要传参数
 * @return string   转换后的字符串
 */
function array_to_String($array, $level = 0) {
    if (!is_array($array)) {
        return "'" . $array . "'";
    }
    $space = ''; //空白
    for ($i = 0; $i <= $level; $i++) {
        $space.="\t";
    }
    $arr = "Array\n$space(\n";
    $c = $space;
    foreach ($array as $k => $v) {
        $k = is_string($k) ? '\'' . addcslashes($k, '\'\\') . '\'' : $k;
        $v = !is_array($v) && (!preg_match("/^\-?[1-9]\d*$/", $v) || strlen($v) > 12) ?
                '\'' . addcslashes($v, '\'\\') . '\'' : $v;
        if (is_array($v)) {
            $arr.="$c$k=>" . array_to_String($v, $level + 1);
        } else {
            $arr.="$c$k=>$v";
        }
        $c = ",\n$space";
    }
    $arr.="\n$space)";
    return $arr;
}

/**
 *  对变量进行 JSON 编码
 */
if (!function_exists('json_encode')) {

    function json_encode($value) {
        $json = new json();
        return $json->encode($value);
    }

}
/**
 *  对JSON格式的字符串进行编码
 */
if (!function_exists('json_decode')) {

    function json_decode($json_value, $bool = false) {
        $json = new json();
        return $json->decode($json_value, $bool);
    }

}

/**
 * 手机号码查询
 * */
function mobile_area($mob) {
    $mob = substr($mob, 0, 7);
    $dat = file_get_contents(PATH_HD_PLUGIN . "/dat/mobile.dat");
    $string = strstr($dat, $mob);
    $num = strpos($string, "\n");
    if (!$num)
        return false;
    $end = substr($string, 0, $num);
    list($a, $area) = explode(",", $end);
    $toCharset = C("charset");
    if (preg_match("/utf8|utf-8/i", $toCharset)) {
        $toCharset = "UTF-8";
    }
    return iconv("gbk", $toCharset, $area);
}

/**
 * 自动加载类
 * @param type $classname
 */
function __autoload($classname) {
    if (substr($classname, -7) == 'Control' && strlen($classname) > 7) {
        $classFile = PATH_APP . '/control/' . $classname . '.php';
    } else {
        $classFile = PATH_HD . '/libs/class/' . $classname . '.class.php';
    }
    if (C("USR_FILES." . $classname)) {
        $classFile = C("USR_FILES." . $classname);
    }
    load_file($classFile);
}

/**
 * 验证扩展是否加载
 * @param type $ext
 */
function extension_exists($ext) {
    $ext = strtolower($ext);
    $loaded_extensions = get_loaded_extensions();
    return in_array($ext, array_change_value_case($loaded_extensions, 0));
}

/**
 * 根据类型获得图像扩展名
 */
if (!function_exists('image_type_to_extension')) {

    function image_type_to_extension($type, $dot = true) {
        $e = array(1 => 'gif', 'jpeg', 'png', 'swf', 'psd', 'bmp',
            'tiff', 'tiff', 'jpc', 'jp2', 'jpf', 'jb2', 'swc',
            'aiff', 'wbmp', 'xbm');
        $type = (int) $type;
        return ($dot ? '.' : '') . $e[$type];
    }

}

/**
 * 获得随机字符串
 * @param number $len 数量
 * @return string
 */
function rand_str($len = 6) {
    $data = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $str = '';
    while (strlen($str) < $len)
        $str.=substr($data, mt_rand(0, strlen($data) - 1), 1);
    return $str;
}

/**
 * 加密方法
 * @param string $data    加密字符串
 * @param string $key         密钥
 */
function encrypt($data, $key = null) {
    return encry::encrypt($data, $key);
}

/**
 * 解密方法
 * @param string $data  解密字符串
 * @param string $key     密钥
 */
function decrypt($data, $key = null) {
    return encry::decrypt($data, $key);
}

/**
 * 替换标签类$attr参数的常量与变量
 * @param void $attr   模板标签属性
 * @return type 变量转换类型1转为PHP语法   2转为变量值
 */
function tpl_format_attr($attr, $type = 1) {
    if (!is_array($attr))
        $attr = array($attr);
    $userConsts = get_defined_constants(true);
    $const = array();
    foreach ($userConsts['user'] as $k => $v) {//获得用户定义常量
        if (!strstr($k, '__'))
            continue;
        $const[$k] = $v;
    }
//替换变量
    $vars = hdView::$vars;
    foreach ($attr as $k => $at) {
//        foreach ($vars as $varName => $varValue) {
//\w+\[?([\'"]?)\w+\1?\]?
//        $replace = $type === 1 ? '<?php echo \0;? >' : '\0';

        switch ($type) {
            case 1:
                $attr[$k] = preg_replace('/\$\w+\[.*\](?!=\[)|\$\w+(?!=[a-z])/', '<?php echo \0;?>', $attr[$k]);
                break;
            case 2:
//                $attr[$k] = preg_replace('/\$\w+\[.*\](?!=\[)|\$\w+(?!=[a-z])/e', '$vars["\"]', $attr[$k]);
                break;
        }
//替换常量
        foreach ($const as $constName => $constValue) {
            $attr[$k] = str_replace($constName, $constValue, $attr[$k]);
        }
    }
    return $attr;
}

/**
 * 变量$varName存在时返回变量值 否则返回$value值
 * @param string $varName  变量名
 * @param void $value      变量不存在时的值
 * @return string
 */
function _default($varName, $value = "") {
    return isset($varName) ? $varName : $value;
}

/**
 * 请求方式
 * @param type $method
 * @param type $args
 */
function _request($method, $varName = null, $html = true) {
    $method = strtolower($method);
    switch ($method) {
        case 'ispost' :
        case 'isget' :
        case 'ishead' :
        case 'isdelete' :
        case 'isput' :
            return strtolower($_SERVER['REQUEST_METHOD']) == strtolower(substr($method, 2));
        case 'get' :
            $data = & $_GET;
            break;
        case 'post' :
            $data = & $_POST;
            break;
        case 'request' :
            $data = & $_REQUEST;
            break;
        case 'session' :
            $data = & $_SESSION;
            break;
        case 'cookie' :
            $data = & $_COOKIE;
            break;
        case 'server' :
            $data = & $_SERVER;
            break;
        case 'globals' :
            $data = & $GLOBALS;
            break;
        default:
            throw_exception('abc');
    }
//获得所有数据
    if (is_null($varName))
        return $data;
    if (isset($data[$varName]) && $html) {
        $data[$varName] = htmlspecialchars($data[$varName]);
    }
    return isset($data[$varName]) ? $data[$varName] : null;
}

/**
 * 设置404错误
 * @param string $msg 错误信息
 * @param string $url 跳转url
 */
function _404($msg = "", $filePath = "") {
    C("DEBUG") && throw_exception($msg);
    Log::write($msg); //写入日志
    if (empty($filePath) && C("ERROR_404")) {
        $filePath = C("ERROR_404");
    }
    //文件不可操作
    if (!is_file($filePath) || !is_readable($filePath)) {
        $filePath = PATH_HD_TPL . '/404.html';
    }
    set_http_state(404);
    include $filePath;
    exit;
}

/**
 * HTTP状态信息设置
 * @param Number $code 状态码
 */
function set_http_state($code) {
    $state = array(
        200 => 'OK', // Success 2xx
// Redirection 3xx
        301 => 'Moved Permanently',
        302 => 'Moved Temporarily ',
        // Client Error 4xx
        400 => 'Bad Request',
        403 => 'Forbidden',
        404 => 'Not Found',
        // Server Error 5xx
        500 => 'Internal Server Error',
        503 => 'Service Unavailable',
    );
    if (isset($state[$code])) {
        header('HTTP/1.1 ' . $code . ' ' . $state[$code]);
        header('Status:' . $code . ' ' . $state[$code]); //FastCGI模式
    }
}

/**
 * 是否为SSL协议
 * @return boolean
 */
function is_ssl() {
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
        return true;
    }
    return false;
}

/**
 * 打印用户定义常量
 */
function print_const() {
    $const = get_defined_constants(true);
    p($const['user']);
}

?>